﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.UI;
public class RayCastCancleWindow : EditorWindow {

    public static GameObject sceneGameObj;

    static List<GameObject> rayObjList = new List<GameObject>();
    static int rayObjCount = 0;

    static Vector3[] fourCorners = new Vector3[4];

    public static bool  drawNameList = false;

    CusGUITable cusguiTable;

    static bool isShowErrorInfo = false;
    static string errorinfo = "检测的对象不能为空";
    static MessageType errorType = MessageType.Error;
    RayCastCancleWindow() {
        this.titleContent = new GUIContent("取消无用射线检测");
        this.minSize = new Vector2(1024,600);
        sceneGameObj = null;
    }

    [MenuItem("便捷工具/资源操作/检测所有raycast = true的对象")]
    public static void ShowWindow() {
        Reset();
        EditorWindow.GetWindow(typeof(RayCastCancleWindow));
    }

    static void Reset()
    {
        drawNameList = false;
        isShowErrorInfo = false;
        errorinfo = "检测的对象不能为空";
        errorType = MessageType.Error;
    }

    void OnGUI() {
        GUILayout.BeginVertical();
        //选择对象
        GUILayout.BeginHorizontal();
        sceneGameObj = (GameObject)EditorGUILayout.ObjectField("检测对象：", sceneGameObj, typeof(GameObject), true);
        if (GUILayout.Button("显示所有的 Raycasht = true 对象"))
        {
            //重置之前数据
            rayObjList.Clear();
            rayObjCount = 0;

            if (sceneGameObj != null)
            {
                GetAllRayObjs(sceneGameObj);
                if (rayObjCount == 0)
                {
                    errorinfo = "未检测到  RayCastTarget = true  的对象";
                    isShowErrorInfo = true;
                    errorType = MessageType.Error;
                    RayCastCancleWindow.drawNameList = false;
                }
                else
                {
                    drawNameList = true;
                    if (cusguiTable == null)
                    {
                        cusguiTable = new CusGUITable(1000, 400, 3);
                        cusguiTable.SetTableTitles(new string[] { "对象名称", "是否射线检测", "类型", "" });
                    }
                    cusguiTable.SetTableContent(rayObjList);
                    isShowErrorInfo = false;
                }
            }
            else
            {
                //提示信息标志位
                isShowErrorInfo = true;
                //取消画界面
                RayCastCancleWindow.drawNameList = false;
            }
            
        }
        GUILayout.EndHorizontal();


        //画表内容
        if (RayCastCancleWindow.drawNameList)
        {
            Debug.Log("总长度"+rayObjList.Count);
            if (cusguiTable != null && sceneGameObj != null)
            {
                cusguiTable.DrawTable();
            }

            GUILayout.BeginHorizontal();
            GUILayout.Space(50);
            if (GUILayout.Button("全不选", GUILayout.Width(100), GUILayout.Height(25)))
            {
                cusguiTable.SetRaycastAll(false);
            }

            if (GUILayout.Button("全选", GUILayout.Width(100), GUILayout.Height(25)))
            {
                cusguiTable.SetRaycastAll(true);
            }

            if (GUILayout.Button("取消文本类型勾选", GUILayout.Width(100), GUILayout.Height(25)))
            {
                cusguiTable.SetTextRaycast(false);
            }

            if (GUILayout.Button("确认设定", GUILayout.Width(100), GUILayout.Height(25)))
            {
                Debug.Log("set raycast value");
                cusguiTable.SetRayToggleValue();
                isShowErrorInfo = true;
                errorinfo = "设置成功";
                errorType = MessageType.Info;
            }

            
            GUILayout.EndHorizontal();
        }

        GUI.skin.box.fontSize = 14;
        GUI.skin.box.alignment = TextAnchor.MiddleCenter;
        GUI.skin.box.normal.textColor = Color.white;
        GUILayout.Box(new GUIContent("说明：\n 1：滚动列表中右侧图片预览框请勿设置，只提供预览作用！\n 2:将对应的Raycast取消后，点击底部的“确认设定按钮”即设置成功 \n 3：若是Hierarchy面板的预制体,记得apply一下 \n 4：“取消文本类型勾选”按钮用于取消所有ui类型为Text的射线检测"),GUILayout.MinWidth(1000));
        //EditorGUILayout.HelpBox("说明：\n 1：滚动列表中右侧图片预览框请勿设置，只提供预览作用！\n 2:将对应的Raycast取消后，点击底部的“确认设定按钮”即设置成功 \n 3：若是Hierarchy面板的预制体,记得apply一下", MessageType.Info);
        //错误信息
        if (isShowErrorInfo)
        {
            EditorGUILayout.HelpBox(errorinfo, errorType);
        }

        GUILayout.EndVertical();
    }

    

    //显示勾选了raycast = true边框
    void OnDrawGizmos()
    {
        foreach (MaskableGraphic g in GameObject.FindObjectsOfType<MaskableGraphic>())
        {
            if (g.raycastTarget)
            {
                RectTransform rectTransform = g.transform as RectTransform;
                rectTransform.GetWorldCorners(fourCorners);
                Gizmos.color = Color.blue;
                for (int i = 0; i < 4; i++)
                    Gizmos.DrawLine(fourCorners[i], fourCorners[(i + 1) % 4]);

            }
        }
    }

    //查找所有包含射线的对象
    void GetAllRayObjs(GameObject go) {
        //Debug.Log("对象子物体个数:");
        //Debug.Log(go.transform.childCount);
        int childCount = go.transform.childCount;
        if (childCount == 0)
        {
            //Debug.Log("x:" + go.name);
            CheckAndPush2List(go);
        }
        else {
            //递归查询
            for (int i = 0; i < go.transform.childCount; i++)
            {
                //显示内容
                //Debug.Log("x:" + go.name+ go.transform.childCount);
                CheckAndPush2List(go);
                GetAllRayObjs(go.transform.GetChild(i).gameObject);
            }
        }
      

        //foreach (MaskableGraphic g in GameObject.FindObjectsOfType<MaskableGraphic>())
        //{
        //    if (g.raycastTarget)
        //    {
        //        Debug.Log(g.gameObject.name);
        //        if (!rayObjList.Contains(g.gameObject)){
        //            rayObjList.Add(g.gameObject);
        //            rayObjCount++;
        //        }
        //    }
        //}
        //Debug.Log(rayObjCount);
    }


    //放入集合中
    void CheckAndPush2List(GameObject go)
    {
        MaskableGraphic mgraphic = go.GetComponent<MaskableGraphic>();
        //Debug.Log(go.gameObject.name);
        if (mgraphic != null && mgraphic.raycastTarget && !rayObjList.Contains(go))
        {
            rayObjList.Add(go);
            rayObjCount++;
        }
    }

}


public class CusGUITable {
    int width = 1000;
    int height = 400;
    int colum = 2;

    //标题宽
    int titleHeight = 45;


    //标题
    string[] titles;
    //内容
    List<GameObject> goList = new List<GameObject>();

    List<GameObject> showGoList = new List<GameObject>();


    bool[] toggleArr;
    int raycastTrueCount = 0;
    List<Boolean> isTrueToggleList = new List<Boolean>();

    //滚动视图位置
    Vector2 scrollPos = Vector2.zero;

    public CusGUITable(int width, int height,int colum) {
        this.width = width;
        this.height = height;
        this.colum = colum;
    }

    //设置标题
    public void SetTableTitles(string[] ts,int titleHeight = 45)
    {
        this.titles = ts;
        this.titleHeight = titleHeight;
    }

    //设置显示的内容
    public void SetTableContent(List<GameObject> goList)
    {
        this.goList = goList;
        toggleArr = new bool[goList.Count];
        this.showGoList.Clear();
        Debug.Log(goList.Count);
        for (int i = 0; i < goList.Count; i++)
        {
            //glRayDic.Add(goList[i].gameObject, goList[i].gameObject.GetComponent<Image>().raycastTarget);
            //Image imgComp = goList[i].gameObject.GetComponent<Image>();
            toggleArr[i] = goList[i].gameObject.GetComponent<MaskableGraphic>().raycastTarget;
            this.showGoList.Add(goList[i]) ;
        }
    }

    // 画表
    public void DrawTable()
    {
        GUILayout.BeginVertical();
        //表头标题
        GUILayout.BeginHorizontal();
        for (int i = 0; i < titles.Length; i++)
        {
            //GUILayout.Label(new GUIContent(titles[i]), GUILayout.Width(this.width / titles.Length), GUILayout.Height(titleHeight));
            DrawTitle(titles[i]);
        }
        GUILayout.EndHorizontal();

        //表内容
        DrawScrollContent();


        for (int i = 0; i < toggleArr.Length; i++)
        {
            if (toggleArr[i])
            {
                GameObject go = this.goList[i];
                if (!this.showGoList.Contains(go))
                {
                    this.showGoList.Add(go);
                }
            }
            else
            {
                this.showGoList.Remove(this.goList[i]);
            }
        }

        GUILayout.Label(new GUIContent("总计："+ this.showGoList.Count), GUILayout.Width(this.width / titles.Length), GUILayout.Height(titleHeight));
        GUILayout.EndVertical();

    }

    // 画标题
    private void DrawTitle(string title)
    {
        GUILayout.Label(new GUIContent(title), GUILayout.Width(this.width / titles.Length), GUILayout.Height(titleHeight));
    }


    // 画滚动视图内容
    private void DrawScrollContent()
    {
        int scrollViewHeight = (height - titleHeight);
        int itemHeight = 1;
        if (goList.Count != 0) {
           itemHeight = scrollViewHeight / goList.Count;
        }

        scrollPos = GUILayout.BeginScrollView(scrollPos, false, true, GUILayout.Width(this.width), GUILayout.Height(scrollViewHeight));
        Sprite mainSprite;
        Texture mainTexture;
        string textInfo = "";

        Debug.Log(goList.Count);
        Debug.Log(toggleArr.Length);
        for (int i = 0; i < goList.Count; i++)
        {
            GUILayout.BeginHorizontal();
            //showGoList[i] = EditorGUILayout.ObjectField("", goList[i], typeof(GameObject), true) as GameObject;
            //GUILayout.Label(new GUIContent(goList[i].name), GUILayout.Width(this.width / titles.Length), GUILayout.Height(itemHeight));
            if (goList[i] == null)
            {
                RayCastCancleWindow.drawNameList = false;
                return;
            }
            goList[i] = EditorGUILayout.ObjectField("", goList[i], typeof(GameObject), true, GUILayout.Width(this.width / titles.Length), GUILayout.Height(20)) as GameObject;
            toggleArr[i] = EditorGUILayout.ToggleLeft("isRaycast", toggleArr[i]);
            // Text，Image,RawImage类型
            //mainSprite = EditorGUILayout.ObjectField("", goList[i].GetComponent<Image>().sprite, typeof(Sprite), true) as Sprite;
            //判断类型：分类处理
            MaskableGraphic mgraphic = goList[i].GetComponent<MaskableGraphic>();
            Type tp = mgraphic.GetType();
            if (tp == typeof(Image))
            {
                EditorGUILayout.LabelField("Image");
                //mainSprite = EditorGUILayout.ObjectField("", goList[i].GetComponent<Image>().sprite, typeof(Sprite), true) as Sprite;
            }
            else if (tp == typeof(RawImage))
            {
                EditorGUILayout.LabelField("RawImage");
                //mainTexture = EditorGUILayout.ObjectField("", goList[i].GetComponent<MaskableGraphic>().mainTexture, typeof(Texture), true) as Texture;
            }
            else if (tp == typeof(Text))
            {
                EditorGUILayout.LabelField("文本  Text");
            }


            mainTexture = EditorGUILayout.ObjectField("", goList[i].GetComponent<MaskableGraphic>().mainTexture, typeof(Texture), true) as Texture;
            GUILayout.EndHorizontal();
        }
        GUILayout.EndScrollView();
    }

    //设置值的内容
    public void SetRayToggleValue()
    {
        for (int i = 0; i < goList.Count; i++)
        {
            goList[i].GetComponent<MaskableGraphic>().raycastTarget = toggleArr[i];
        }
    }


    public void SetRaycastAll(bool isRayCast)
    {
        for (int i = 0; i < toggleArr.Length; i++)
        {
            toggleArr[i] = isRayCast;
        }
    }


    //设置文本类型射线
    public void SetTextRaycast(bool isRaycast)
    {
        for (int i = 0; i < goList.Count; i++)
        {
            MaskableGraphic mgraphic = goList[i].GetComponent<MaskableGraphic>();
            Type tp = mgraphic.GetType();
            if (tp == typeof(Text))
            {
                toggleArr[i] = false;
                this.showGoList.Remove(goList[i]);
            }

        }
        
    }
}
